﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
using AutoLoL.Entities;
using AutoLoL.Logic.Parsers;

namespace AutoLoL.Logic.Repositories
{
    public class RafChampionRepository : IChampionRepository
    {
        private ReadOnlyCollection<Champion> _champions;

        public RafChampionRepository()
        {
        }

        public Champion GetByName(string championName)
        {
            if (string.IsNullOrEmpty(championName))
            {
                return null;
            }

            return GetAll().Where(c => c.Name.ToLower().Equals(championName.ToLower())).SingleOrDefault();
        }

        public ReadOnlyCollection<Champion> GetAll()
        {
            if (_champions != null)
            {
                return _champions;
            }

            List<Champion> champions = new List<Champion>();

            Func<string, bool> filter = ((path) =>
                path.ToLower().StartsWith("data/characters")
                && path.ToLower().EndsWith(".inibin")
                && path.Split('/').Length == 4);

            ReadOnlyCollection<RafFile> rafFiles = RafManager.Instance.GetFiles(filter);

            foreach (RafFile rafFile in rafFiles)
            {
                RafManager.Instance.SetRafFileData(rafFile);

                Dictionary<uint, InibinEntry> data;

                try
                {
                    if (rafFile.Data.Length <= 260) continue;
                    
                    data = InibinParser.ParseBytes(rafFile.Data);
                }catch{continue;}


                if (data.ContainsKey((uint)InibinKeys.Character.IS_CHAMPION) && data[(uint)InibinKeys.Character.IS_CHAMPION].GetString().ToLower().Equals("true"))
                {
                    string directoryName = rafFile.PathChunks[rafFile.PathChunks.Length - 2];

                    // Parse FC
                    string fckName = data[(uint)InibinKeys.Character.FCK_NAME].GetString();
                    string fckDescription = data[(uint)InibinKeys.Character.FCK_DESCRIPTION].GetString();
                    string fckLore = data[(uint)InibinKeys.Character.FCK_LORE].GetString();

                    string name = FontConfigParser.Instance.GetValue(fckName);
                    string description = FontConfigParser.Instance.GetValue(fckDescription);
                    string lore = FontConfigParser.Instance.GetValue(fckLore);

                    string iconFilename = data[(uint)InibinKeys.Character.PATH_ICON_DDS].GetString();
                    string iconPath = string.Format("data/characters/{0}/info/{1}", directoryName, iconFilename);
                    RafFile iconRafFile = RafManager.Instance.GetFile(iconPath);

                    //Had to add this to prevent breakage... We can use this as a HotFix for now not sure what is really going on here.
                    if (iconRafFile == null) continue;
                    
                    RafManager.Instance.SetRafFileData(iconRafFile);

                    BitmapSource iconBitmap = null;
                    if (iconFilename.ToLower().EndsWith(".dds"))
                    {
                        iconBitmap = ImageParser.DdsToBitmapSource(iconRafFile.Data);
                    }
                    else if (iconFilename.ToLower().EndsWith(".tga"))
                    {
                        iconBitmap = ImageParser.TgaToBitmapSource(iconRafFile.Data);
                    }

                    if (name != null && description != null && lore != null && iconBitmap != null && directoryName != null && data != null)
                    {
                        Champion champion = new Champion();
                        champion.Name = name;
                        champion.Description = description;
                        champion.Lore = lore;
                        champion.IconBitmapImage = iconBitmap;
                        champion.DirectoryName = directoryName;
                        champion.Data = data;

                        champions.Add(champion);
                    }
                }
            }

            champions.Sort((x1, x2) => x1.Name.CompareTo(x2.Name));

            _champions = new ReadOnlyCollection<Champion>(champions);

            return _champions;
        }

        public void SetSkins(Champion champion)
        {
            List<Skin> skins = new List<Skin>();

            for (int i = 0; i < InibinKeys.CHARACTER_MODEL_DDS_PATH_KEYS.Length; i++)
            {
                if (champion.Data.ContainsKey(InibinKeys.CHARACTER_MODEL_DDS_PATH_KEYS[i]))
                {
                    string modelDdsFilename = champion.Data[(uint)InibinKeys.CHARACTER_MODEL_DDS_PATH_KEYS[i]].GetString();
                    string modelDdsPath = string.Format("data/characters/{0}/{1}", champion.DirectoryName, modelDdsFilename);
                    RafFile modelDdsRafFile = RafManager.Instance.GetFile(modelDdsPath);

                    string modelSknFilename = champion.DirectoryName + ".skn";
                    if (champion.Data.ContainsKey(InibinKeys.CHARACTER_MODEL_SKN_PATH_KEYS[i]))
                    {
                        modelSknFilename = champion.Data[InibinKeys.CHARACTER_MODEL_SKN_PATH_KEYS[i]].GetString();
                    }

                    string modelSkinPath = string.Format("data/characters/{0}/{1}", champion.DirectoryName, modelSknFilename);
                    RafFile modelSkinRafFile = RafManager.Instance.GetFile(modelSkinPath);

                    string skinName = "Base";
                    if (i > 0)
                    {
                        string fckSkin = string.Format("game_character_skin_displayname_{0}_{1}", champion.DirectoryName, i);
                        if (FontConfigParser.Instance.ContainsKey(fckSkin))
                        {
                            skinName = FontConfigParser.Instance.GetValue(fckSkin);
                        }
                        else
                        {
                            skinName = "Unknown";
                        }
                    }

                    Skin skin = new Skin(skinName, modelSkinRafFile, modelDdsRafFile, modelSknFilename, modelDdsFilename);
                    skins.Add(skin);
                }
            }

            champion.Skins = new ReadOnlyCollection<Skin>(skins);
        }
    }
}
